package com.kx.gateway.filter;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.jsonwebtoken.Jwts;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.http.HttpHeaders;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import reactor.netty.ByteBufFlux;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 过滤器
 * @author Sun
 * @date 2021/8/4 17:29
 */
public class AutoFilter implements GlobalFilter, Ordered {
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {

        String requestUrl=exchange.getRequest().getPath().toString();
        if(exchange.getRequest().getMethod().matches("OPTIONS")){

        }

        if(!"/kx/user/signin".equals(requestUrl)){
            //不是登陆，校验token
            List<String> tokens = exchange.getRequest().getHeaders().get("token");

            //设置一个判断标志位
            boolean checkToken=true;
            if(tokens!=null){
                //拿到token
                String token=tokens.get(0);
                try {
                    Jwts.parser().setSigningKey("qianfeng".getBytes()).parseClaimsJws(token).getBody();
                }catch (Exception e){
                    checkToken=false;
                }
            }else{
                //没有token
                checkToken=false;
            }

            if(!checkToken){
                //返回 请使用一个有效的token
                ServerHttpResponse response = exchange.getResponse();
                HttpHeaders headers = response.getHeaders();
                headers.add("Content-Type","application/json;charset=UTF-8");
                return response.writeAndFlushWith(
                        Flux.just(
                                ByteBufFlux.just(
                                        response.bufferFactory().wrap(getWrapData())
                                )
                        )
                );
            }
        }


        return chain.filter(exchange).then(
                Mono.fromRunnable(new Runnable() {
                    @Override
                    public void run() {
                        //彻底处理跨域问题
                        HttpHeaders headers=exchange.getResponse().getHeaders();
                        //移除六种导致跨域问题的头信息
                        headers.remove("Access-Control-Allow-Credentials");
                        headers.remove("Access-Control-Allow-Origin");
                        headers.remove("Access-Control-Allow-Methods");
                        headers.remove("Access-Control-Max-Age");
                        headers.remove("Access-Control-Allow-Headers");
                        headers.remove("Access-Control-Expose-Headers");
                        //添加不能导致跨域错误的头
                        headers.add("Access-Control-Allow-Credentials","true");
                        headers.add("Access-Control-Allow-Origin","*");
                        headers.add("Access-Control-Allow-Methods","GET, POST, DELETE, PUT, OPTIONS");
                        headers.add("Access-Control-Max-Age","3600");
                        headers.add("Access-Control-Allow-Headers","Origin, X-Requested-With, Content-Type, Accept, new-token");
                        headers.add("Access-Control-Expose-Headers","Location");
                    }
                })
        );
    }

    @Override
    public int getOrder() {
        return 1;
    }


    /**
     * 身份不合法的json的封装
     */
    private byte [] getWrapData(){
        Map<String,String> map=new HashMap<>();
        map.put("code","401");
        map.put("msg","请使用一个有效的token");
        map.put("result",null);
        try {
            return new ObjectMapper().writeValueAsString(map).getBytes();
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }
        return "".getBytes();
    }
}
